package cn.bby.query.server.domain.service.fetcher;

import cn.bby.jtk.base.exception.ServiceException;
import cn.bby.query.base.constant.AdvQueryErrorCode;
import cn.bby.query.base.constant.QueryCondition;
import cn.bby.query.base.model.req.Filter;
import cn.bby.query.base.model.req.QueryRequest;
import cn.bby.query.base.model.req.QueryResponse;
import cn.bby.query.server.domain.agg.metadata.entity.InterfaceInfo;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author ben
 * @since 2025/4/20 00:29
 */
@Slf4j
@Service("KeyFullDataFetcher.number")
public class NumberKeyDataFetcherImpl extends BaseDataFetcherImpl {

    @Override
    public void fetchData(InterfaceInfo interfaceInfo) {
        // todo 删除
        dataStorageManager.deleteDataStruct(List.of(interfaceInfo));
        dataStorageManager.initDataStruct(interfaceInfo);
        List<Filter> filters = new ArrayList<>();
        QueryRequest queryRequest = new QueryRequest()
                .setPage(1)
                .setFilters(filters)
                .setSize(pageSize)
                .setSorts(List.of(new QueryRequest.Sort(interfaceInfo.getPrimaryField())));
        Filter idFilter = new Filter()
                .setField(interfaceInfo.getPrimaryField())
                .setCondition(QueryCondition.GREAT_THEN);
        doRequest(interfaceInfo, queryRequest, data -> {
            queryRequest.getFilters().add(idFilter);
            queryRequest.setIgnoreTotal(true);
            handleDataPage(idFilter, queryRequest, interfaceInfo, data);
        });
    }

    @Override
    public void reFetchDataAll(InterfaceInfo interfaceInfo) {
        QueryRequest queryRequest = new QueryRequest()
                .setPage(1)
                .setFilters(new ArrayList<>())
                .setSize(pageSize)
                .setSorts(List.of(new QueryRequest.Sort(interfaceInfo.getPrimaryField())));
        Filter idFilter = new Filter()
                .setField(interfaceInfo.getPrimaryField())
                .setCondition(QueryCondition.GREAT_THEN);
        doRequest(interfaceInfo, queryRequest, data -> {
            queryRequest.getFilters().add(idFilter);
            queryRequest.setIgnoreTotal(true);
            handleReloadDataPage(idFilter, queryRequest, interfaceInfo, data);
        });
    }

    @Override
    public void reFetchData(InterfaceInfo interfaceInfo, Set<String> keyValues) {
        if (CollUtil.isEmpty(keyValues)) {
            return;
        }
        QueryRequest queryRequest = new QueryRequest()
                .setPage(1)
                .setIgnoreTotal(true)
                .setFilters(List.of(
                                new Filter(
                                        interfaceInfo.getPrimaryField(),
                                        QueryCondition.EQUALS,
                                        new ArrayList<>(keyValues))
                        )
                )
                .setSize(keyValues.size());
        doRequest(interfaceInfo, queryRequest, data -> {
            List<JSONObject> dataSet = data.getDataSet();
            if (CollUtil.isEmpty(dataSet)) {
                return;
            }
            dataStorageManager.updateDataBatchById(interfaceInfo, keyValues, data.getDataSet());
        });
    }

    private void handleDataPage(Filter idFilter, QueryRequest queryRequest, InterfaceInfo interfaceInfo, QueryResponse<JSONObject> data) {
        if (data.getTotal() == 0) {
            dataStorageManager.finishLoad(interfaceInfo);
            return;
        }
        List<JSONObject> dataSet = data.getDataSet();
        String offsetId = CollUtil.getLast(dataSet).getString(interfaceInfo.getPrimaryField());
        if (offsetId == null) {
            throw new ServiceException(AdvQueryErrorCode.FIELD_NOT_EXIST, "主键读取失败：" + interfaceInfo.getPrimaryField());
        }
        dataStorageManager.saveData(interfaceInfo, dataSet, offsetId);
        if (data.getDataSet().size() < pageSize) {
            // 最后一页
            dataStorageManager.finishLoad(interfaceInfo);
            return;
        }
        // 后续页
        idFilter.setValues(List.of(offsetId));
        doRequest(interfaceInfo, queryRequest, data1 -> handleDataPage(idFilter, queryRequest, interfaceInfo, data1));
    }

    private void handleReloadDataPage(Filter idFilter, QueryRequest queryRequest, InterfaceInfo interfaceInfo, QueryResponse<JSONObject> data) {
        if (data.getTotal() == 0) {
            return;
        }
        List<JSONObject> dataSet = data.getDataSet();
        String offsetId = CollUtil.getLast(dataSet).getString(interfaceInfo.getPrimaryField());
        if (offsetId == null) {
            throw new ServiceException(AdvQueryErrorCode.FIELD_NOT_EXIST, "主键读取失败：" + interfaceInfo.getPrimaryField());
        }
        Set<String> keyValues = dataSet.stream()
                .map(d -> d.getString(interfaceInfo.getPrimaryField()))
                .collect(Collectors.toSet());
        dataStorageManager.updateDataBatchById(interfaceInfo, keyValues, data.getDataSet());
        if (data.getDataSet().size() < pageSize) {
            log.warn("数据加载完成：{}", interfaceInfo.getInterfaceName());
            return;
        }
        // 后续页
        idFilter.setValues(List.of(offsetId));
        doRequest(interfaceInfo, queryRequest, data1 -> handleReloadDataPage(idFilter, queryRequest, interfaceInfo, data1));
    }

}
